# 导入os库，用于操作文件
import os


# 定义函数，用于读取学生信息
def load_students(filename):
    # 创建一个空列表，用于存储学生信息
    students = []
    # 判断指定文件是否存在
    if os.path.exists(filename):
        # 打开文件，以只读模式进行操作，并将其句柄赋给变量file
        with open(filename, 'r') as file:
            # 逐行读取文件内容
            for line in file:
                # 去除每行首尾的空格，并按逗号进行内容分割，将结果赋给变量parts
                parts = line.strip().split(',')
                # 创建一个字典，将分割后的内容与固定的键一一对应，并将结果赋给变量student
                student = {
                    'stu_no': parts[0],  # 学号
                    'stu_name': parts[1],  # 姓名
                    'dorm_no': parts[2],  # 宿舍号
                    'stu_age': parts[3],  # 年龄
                    'stu_sex': parts[4],  # 性别
                    'stu_native': parts[5],  # 籍贯
                    'stu_major': parts[6]  # 专业
                }
                # 将学生信息字典添加到学生列表中
                students.append(student)
    # 返回学生列表
    return students


# 定义函数，用于保存学生信息到文件中
def save_students(filename, students):
    # 打开文件，以写入模式进行操作，并将其句柄赋给变量file
    with open(filename, 'w') as file:
        # 遍历学生列表中的每个学生字典
        for student in students:
            # 将学生信息转换为字符串形式，并以逗号作为分隔符，将其写入文件中
            student_str = f"{student['stu_no']},{student['stu_name']},{student['dorm_no']},{student['stu_age']},{student['stu_sex']},{student['stu_native']},{student['stu_major']}\n"
            # 将学生信息写入文件
            file.write(student_str)


# 定义函数，用于交换学生列表中的两个学生的位置
def swap(students, i, j, flag):
    # 根据flag的不同进行不同的判断和交换操作
    if flag == 1 and students[i]['stu_no'] > students[j]['stu_no']:
        # 使用Python的多重赋值同时交换两个变量的值
        students[i], students[j] = students[j], students[i]
    elif flag == 2 and students[i]['stu_name'] > students[j]['stu_name']:
        students[i], students[j] = students[j], students[i]
    elif flag == 3:
        if students[i]['dorm_no'] > students[j]['dorm_no'] or (
                students[i]['dorm_no'] == students[j]['dorm_no'] and students[i]['stu_no'] > students[j]['stu_no']):
            students[i], students[j] = students[j], students[i]


# 定义函数，用于向学生列表中插入学生信息
def insert_student(students, student, flag):
    # 在学生列表的末尾添加新的学生信息
    students.append(student)
    # 从学生列表的最后一个学生开始，向前依次比较并交换学生的位置，以实现插入排序
    for i in range(len(students) - 1, 0, -1):
        swap(students, i - 1, i, flag)


# 定义函数，用于打印学生信息
def print_student_info(student):
    # 打印学生信息，使用对齐符号进行格式调整
    print(
        f"*  {student['stu_no']:<12} {student['stu_name']:<10} {student['stu_sex']:<5} {student['stu_age']:<5} {student['stu_native']:<12} {student['stu_major']:<15} {student['dorm_no']:<8} *")


# 定义函数，用于打印指定宿舍的学生信息
def print_dorm_info(students, dorm_no):
    # 根据宿舍号筛选出属于该宿舍的学生，并将其存储到一个新的列表中
    dorm_students = [s for s in students if s['dorm_no'] == dorm_no]
    # 对新的列表进行排序，根据学号进行升序排序
    dorm_students.sort(key=lambda s: s['stu_no'])
    # 打印宿舍的学生信息表头
    print(f"\n该宿舍人数为 {len(dorm_students)}")
    print("***********************************************************************    ")
    print("*  学号        姓名      性别 年龄 籍贯        专业           宿舍号  *")
    # 遍历宿舍的学生信息列表，逐行打印学生信息
    for student in dorm_students:
        print_student_info(student)
    print("***********************************************************************")


# 定义函数，用于判断两个字符串是否匹配
def judge_marry(str1, str2):
    i, j = 0, 0
    # 使用双指针的方法进行匹配比较
    while j < len(str2) and i < len(str1):
        if str1[i] == str2[j]:
            j += 1
        i += 1
    # 返回比较结果
    return j == len(str2)


# 定义函数，用于在学生列表中模糊查询学生信息
def dim_search(students, keyword, flag):
    found = False
    # 根据不同的flag进行不同的查询操作
    if flag == 1:
        for student in students:
            if judge_marry(student['stu_no'], keyword):
                # 打印匹配的学生信息，并将found置为True
                print_student_info(student)
                found = True
    elif flag == 2:
        for student in students:
            if judge_marry(student['stu_name'], keyword):
                print_student_info(student)
                found = True
    # 如果没有找到匹配的结果，则打印提示信息
    if not found:
        print("\n!!! 没有匹配结果\n")


# 定义函数，用于对学生列表进行冒泡排序
def bubble_sort(students, flag):
    n = len(students)
    for i in range(n):
        for j in range(1, n):
            swap(students, j - 1, j, flag)
    # 根据不同的flag打印不同的排序完成提示信息
    if flag == 1:
        print("\n已完成按*学号*的排序  可输入 4 进行展示\n")
    elif flag == 2:
        print("\n已完成按*姓名*的排序  可输入 4 进行展示\n")
    elif flag == 3:
        print("\n已完成按*宿舍号*的排序  可输入 4 进行展示\n")


# 定义函数，用于在学生列表中进行二分查找
def binary_search(students, keyword, flag):
    low, high = 0, len(students) - 1
    while low <= high:
        mid = (low + high) // 2
        if flag == 1:
            if students[mid]['stu_no'] > keyword:
                high = mid - 1
            elif students[mid]['stu_no'] < keyword:
                low = mid + 1
            else:
                # 打印找到的学生信息，并返回
                print_student_info(students[mid])
                return
        elif flag == 2:
            if students[mid]['stu_name'] > keyword:
                high = mid - 1
            elif students[mid]['stu_name'] < keyword:
                low = mid + 1
            else:
                print_student_info(students[mid])
                return
        elif flag == 3:
            if students[mid]['dorm_no'] > keyword:
                high = mid - 1
            elif students[mid]['dorm_no'] < keyword:
                low = mid + 1
            else:
                # 打印指定宿舍的学生信息，并返回
                print_dorm_info(students, students[mid]['dorm_no'])
                return
    # 如果没有找到匹配的结果，则打印提示信息
    print("\n查无此人 请检查您的输入是否正确\n")


# 主函数
def main():
    # 设置文件名
    filename = 'students.txt'
    # 从文件中读取学生信息，并将结果赋给students列表
    students = load_students(filename)

    while True:
        print("************************************************************")
        print("* 宿舍管理查询系统                                        *")
        print("* 输入相应数字可实现对应功能                               *")
        print("* 1 录入学生信息                                           *")
        print("* 2 对学生信息排序                                         *")
        print("* 3 查询学生信息                                           *")
        print("* 4 插入学生信息                                           *")
        print("* 5 对学生信息模糊查询                                     *")
        print("* 6 对学生信息删除修改                                     *")
        print("* 0 退出本系统                                             *")
        print("************************************************************")
        # 用户输入选择数字
        choice = input("请输入您的选择: ")

        if choice == '0':
            # 用户选择退出系统，保存学生信息到文件中，并退出循环
            save_students(filename, students)
            break
        elif choice == '1':
            while True:
                print("************************************************************")
                print("* 录入学生信息平台                                        *")
                print("* 1 开始录入                                               *")
                print("* 0 返回主界面                                             *")
                print("************************************************************")
                # 用户输入录入操作数字
                sub_choice = input("请输入您的操作: ")
                if sub_choice == '0':
                    break
                elif sub_choice == '1':
                    num = int(input("请输入您要录入的学生人数: "))
                    for i in range(num):
                        student = {
                            'stu_no': input(f"第 {i + 1} 个学生学号: "),
                            'stu_name': input(f"第 {i + 1} 个学生姓名: "),
                            'stu_age': input(f"第 {i + 1} 个学生年龄: "),
                            'stu_sex': input(f"第 {i + 1} 个学生性别: "),
                            'stu_native': input(f"第 {i + 1} 个学生籍贯: "),
                            'stu_major': input(f"第 {i + 1} 个学生专业: "),
                            'dorm_no': input(f"第 {i + 1} 个学生宿舍号: ")
                        }
                        students.append(student)
        elif choice == '2':
            print("************************************************************")
            print("* 1 按学号排序                                            *")
            print("* 2 按姓名排序                                            *")
            print("* 3 按宿舍号排序                                          *")
            print("************************************************************")
            # 用户输入排序方式数字
            flag = int(input("请选择排序方式: "))
            # 对学生列表进行排序
            bubble_sort(students, flag)
        elif choice == '3':
            # 用户输入要查询的学生学号
            stu_no = input("请输入要查询的学生学号: ")
            # 在学生列表中进行二分查找
            binary_search(students, stu_no, 1)
        elif choice == '4':
            student = {
                'stu_no': input("请输入插入学生的学号: "),
                'stu_name': input("请输入插入学生的姓名: "),
                'stu_age': input("请输入插入学生的年龄: "),
                'stu_sex': input("请输入插入学生的性别: "),
                'stu_native': input("请输入插入学生的籍贯: "),
                'stu_major': input("请输入插入学生的专业: "),
                'dorm_no': input("请输入插入学生的宿舍号: ")
            }
            print("************************************************************")
            print("* 1 按学号插入                                            *")
            print("* 2 按姓名插入                                            *")
            print("* 3 按宿舍号插入                                          *")
            print("************************************************************")
            # 用户输入插入方式数字
            flag = int(input("请选择插入方式: "))
            # 将学生信息插入到学生列表中
            insert_student(students, student, flag)
        elif choice == '5':
            print("************************************************************")
            print("* 1 按学号模糊查询                                        *")
            print("* 2 按姓名模糊查询                                        *")
            print("************************************************************")
            # 用户输入查询方式数字
            flag = int(input("请选择查询方式: "))
            # 用户输入查询关键字
            keyword = input("请输入查询关键字: ")
            # 在学生列表中进行模糊查询
            dim_search(students, keyword, flag)


# 如果作为独立脚本运行，则执行main函数
if __name__ == "__main__":
    main()